﻿using System;
using System.Collections.Generic;
using System.Text;
using TCCHWLib;
using TCCHWLib.Commands;
using System.Windows.Forms;
using System.Collections;
using TCCSWLib;
using System.Drawing;

namespace TCCCompiler
{
    public class Compiler
    {
        public Compiler()
        {

        }

        public void Compile(List<string> rtbData, List<string> rtbCode, TreeView tvData, TreeView tvCode, RichTextBox rtbOutput)
        {
            rtbOutput.Clear();
            tvCode.Nodes.Clear();
            tvData.Nodes.Clear();

            lines = rtbCode;
            DataLines = rtbData;

            commentedAndEmptyLinesIndex = new int[rtbCode.Count];
            DataCommentedAntEmptyLinesIndex = new int[rtbData.Count];

            int commentedAndEmptyLinesCount = CheckForSpacesAndComments(lines, rtbCode.Count, commentedAndEmptyLinesIndex);
            int DataCommentedAndEmptyLinesCount = CheckForSpacesAndComments(DataLines, rtbData.Count, DataCommentedAntEmptyLinesIndex);

            RemoveCommentedAndEmptyLines(lines, rtbCode.Count, commentedAndEmptyLinesIndex, commentedAndEmptyLinesCount);
            RemoveCommentedAndEmptyLines(DataLines, rtbData.Count, DataCommentedAntEmptyLinesIndex, DataCommentedAndEmptyLinesCount);

            TreeNode node = new TreeNode();
            TreeNode NewDataNode = new TreeNode();

            LineParser Parse = new LineParser(lines, node, DataLines, NewDataNode);
            tvCode.Nodes.Add(Parse.root);
            tvData.Nodes.Add(Parse.root2);
            //TreeNode data=  DrawDataTree(Parse.LiteralTableDataName, Parse.LiteralTableDataType);

            TreeNode n = (TreeNode)Parse.root.Clone();
            TreeNode data = (TreeNode)Parse.root2.Clone();
            Dictionary<BatchCommand, PriorityKey> batches;
            command_generator cmg = new command_generator(n, data);
            batches = cmg.start();
            int i = 1;
            int count = 0;
            foreach (KeyValuePair<BatchCommand, PriorityKey> batch in batches)
            {
                PriorityKey pr = (PriorityKey)batch.Value;
                BatchCommand batch_command = (BatchCommand)batch.Key;
                rtbOutput.SelectionColor = Color.SteelBlue;
                rtbOutput.SelectionIndent = 0;
                rtbOutput.SelectionHangingIndent = 20;
                rtbOutput.AppendText(String.Format("{0} ==============< Batch #{1} [{2},{3}] >==============\n\n",
                    ((count != 0) ? "\n" : ""), count++, pr.Phase.ToString(), pr.Sequence.ToString()));

                rtbOutput.SelectionColor = Color.Black;
                rtbOutput.SelectionIndent = 8;
                foreach (ICommand c in batch_command.CommandList)
                {
                    rtbOutput.AppendText(c + "\n");
                }
                i++;
                JobScheduler.Instance.AddJob(batch.Key, batch.Value);
            }
            JobScheduler.Instance.FinalizeJob();
        }
        #region Variables

        List<string> lines;
        List<string> DataLines;

        string[] commentedLines;

        int[] commentedAndEmptyLinesIndex;
        int[] DataCommentedAntEmptyLinesIndex;

        string[] commentSeparator = new string[1] { "//" };

        #endregion

        #region Helper Functions

        int CheckForSpacesAndComments(List<string> CodeLines, int CodeCount, int[] THECodeCommentedAndEmptyLinesIndex)
        {
            int commentedAndEmptyLinesCount = 0;
            commentedLines = new string[5];
            for (int i = 0; i < CodeCount; i++)
            {
                commentedLines[0] = CodeLines[i];
                commentedLines = CodeLines[i].Split(commentSeparator, StringSplitOptions.None);
                CodeLines[i] = commentedLines[0];
                CodeLines[i] = CodeLines[i].Trim();
                if (CodeLines[i] == "")
                {
                    THECodeCommentedAndEmptyLinesIndex[commentedAndEmptyLinesCount] = i;
                    commentedAndEmptyLinesCount++;
                }
            }
            return commentedAndEmptyLinesCount;
        }
        void RemoveCommentedAndEmptyLines(List<string> TheLines, int TheCodeLineCount, int[] Indexes, int CommentedAndEmptyLinesCountOfTHEcode)
        {
            for (int i = 0; i < CommentedAndEmptyLinesCountOfTHEcode; i++)
            {
                if (i >= Indexes.Length)
                    break;

                Remove(TheLines, Indexes[i]);
                DecrementIndexes(Indexes, i, CommentedAndEmptyLinesCountOfTHEcode);
                TheCodeLineCount--;
            }
            //lines[Indexes[i]].Remove(Indexes[i], 1);

        }
        void DecrementIndexes(int[] intArray, int startingIndex, int endingIndex)
        {
            for (int i = startingIndex; i < endingIndex; i++)
                intArray[i]--;
        }
        void Remove(List<string> stringArray, int index)
        {
            for (int i = index; i < stringArray.Count - 1; i++)
                stringArray[i] = stringArray[i + 1];
            stringArray[stringArray.Count - 1] = null;
        }

        #endregion
    }
}
